﻿using System;
using System.Collections.Generic;
using System.Configuration;
using Citi.RoutineBase;
using Citi.Scheduler.RunnerApplication.SchedulerUI;
using Citi.Helpers;
using Citi.BOExtraction.SchedulerUI.SchedulerWcf;
using System.IO;

namespace Citi.BOExtraction.SchedulerUI
{
    public class Extraction : IExecutableRoutine
    {
        private static string BOExtractor { get { return ConfigurationManager.AppSettings["BOExtractor"]; } }
        private static Execution RunnerExecution = new Execution();

        public IEnumerable<RoutineParameter> Parameters
        {
            get
            {
                return new List<RoutineParameter> { 
                    new RoutineParameter{ Description = "Report name", Name = "ReportName", Nullable= false, Required = true, Type = typeof(string)},
                    new RoutineParameter{ Description = "SSO Url", Name = "Url", Nullable= false, Required = true, Type = typeof(string)},
                    new RoutineParameter{ Description = "User to log on BO", Name = "UserLogin", Nullable= false, Required = true, Type = typeof(string)},
                    new RoutineParameter{ Description = "Browser. 0 - Internet Explorer. 1 - Chrome.", Name = "Browser", Nullable= false, Required = true, Type = typeof(short)},
                    new RoutineParameter{ Description = "Path name to save the report", Name = "PathToSave", Nullable= false, Required = true, Type = typeof(string)},
                    new RoutineParameter{ Description = "BO Parameters", Name = "BOParameters", Nullable = true, Required = false, Type = typeof(string)},
                    new RoutineParameter{ Description = "Join sheets and save a XLSX file", Name = "JoinSheets", Nullable= false, Required = true, Type = typeof(bool)},
                    new RoutineParameter{ Description = "When Joining Sheet please provide a new sheet name", Name = "NewSheetName", Nullable= true, Required = false, Type = typeof(string)},
                    new RoutineParameter{ Description = "If you want to start a routine when it's finished, insert the Routine Id.", Name ="SuccessorRoutineId", Nullable = true, Required = false, Type = typeof(int)},
                    new RoutineParameter{ Description = "BO Url. When you need access more than one URL to get BO access. (Separated by ||)", Name = "BOUrl", Nullable= true, Required = false, Type = typeof(string)},
                    new RoutineParameter{ Description = "Block New window?", Name = "NewWindowNoAction", Nullable = true, Required = false, Type = typeof(bool)},
                };
            }
        }

        public void Rollback(ref ICurrentAction currentAction, Dictionary<string, object> parameters)
        {
            FillParameters(parameters, parameters["ReportName"].ToString(), string.Empty);
            RunnerExecution.Rollback(ref currentAction, parameters);
        }

        public void Start(DateTime scheduledDate, ref ICurrentAction currentAction, Dictionary<string, object> parameters)
        {
            var reportName = parameters["ReportName"].ToString();
            var url = parameters["Url"].ToString();
            var userLogin = parameters["UserLogin"].ToString();
            var pathToSave = parameters["PathToSave"].ToString();
            var browser = parameters.ContainsKey("Browser") ? parameters["Browser"].ToString() : "0";
            var joinSheets = bool.Parse(parameters["JoinSheets"].ToString());
            var newWindowNoAction = parameters.ContainsKey("NewWindowNoAction") ? bool.Parse(parameters["NewWindowNoAction"].ToString()) : false;
            var newSheetName = parameters.ContainsKey("NewSheetName") ? parameters["NewSheetName"].ToString() : string.Empty;
            var boParameters = parameters.ContainsKey("BOParameters") ? parameters["BOParameters"].ToString() : null;
            var successorRoutineId = parameters.ContainsKey("SuccessorRoutineId") ? parameters["SuccessorRoutineId"].ToString() : null;
            var boUrl = parameters.ContainsKey("BOUrl") ? parameters["BOUrl"].ToString() : string.Empty; ;

            if (pathToSave.EndsWith(".xlsx") && joinSheets)
                pathToSave = pathToSave.Substring(0, pathToSave.Length - 1);

            var args = new Dictionary<string, string>
            {
                {"reportName", reportName},
                {"url", url},
                {"userLogin", userLogin},
                {"pathToSave", pathToSave},
                {"joinSheets", joinSheets.ToString()},
                {"newSheetName", newSheetName},
                {"browser", browser},
                {"parameters", boParameters},
                {"boUrl", boUrl},
                {"newWindowNoAction", newWindowNoAction.ToString()}
            };

            var arguments = string.Empty;

            foreach (var arg in args)
                arguments += string.Format(@"-{0} ""{1}"" ", arg.Key, arg.Value);

            FillParameters(parameters, reportName, arguments);

            RunnerExecution.Start(scheduledDate, ref currentAction, parameters);

            if (!File.Exists(pathToSave))
                throw new Exception(string.Format("File '{0}' does not exist", pathToSave));

            try
            {
                ExcelHelper.ValidateExcelFile(pathToSave, null);
            }
            catch (Exception e)
            { 
                throw new Exception(string.Format("File '{0}' is corrupted. Please check it.", pathToSave));
            }

            if (joinSheets && Path.GetExtension(pathToSave) == ".xls")
            {
                currentAction.Description = "Joining sheets";
                //MergeSheets(pathToSave, newSheetName);
                var path = MergeExcel.MergeSheets(pathToSave, pathToSave, newSheetName, 1, 1);
                File.Delete(pathToSave);
            }

            if (!string.IsNullOrWhiteSpace(successorRoutineId))
            {
                currentAction.Description = "Scheduling successor routine";

                using (var client = new ScheduleClient())
                    client.ExecuteRoutineOnDemandById(int.Parse(successorRoutineId), null);

                currentAction.Description = "Successor routine scheduled. It will be executed as soon as possible";
            }
            else
                currentAction.Description = "Successor routine was not set";

            //BusinessObjectsExtract.StartExtraction(null, reportName, url, userLogin, pathToSave, joinSheets, newSheetName);
        }

        private void FillParameters(Dictionary<string, object> parameters, string reportName, string arguments)
        {
            foreach (var parameter in Parameters)
                parameters.Remove(parameter.Name);

            if (parameters.ContainsKey(Execution.ApplicationPathName))
                parameters.Remove(Execution.ApplicationPathName);

            if (parameters.ContainsKey(Execution.ApplicationArguments))
                parameters.Remove(Execution.ApplicationArguments);

            if (parameters.ContainsKey(Execution.LogApplicationPathName))
                parameters.Remove(Execution.LogApplicationPathName);

            parameters.Add("UnlockLockMachine", "false");
            parameters.Add(Execution.ApplicationPathName, BOExtractor);
            parameters.Add(Execution.ApplicationArguments, arguments);
            parameters.Add(Execution.LogApplicationPathName, string.Format(ConfigurationManager.AppSettings["LogPath"], FileHelper.MakeValidFileName(reportName)));
        }

        public void Stop(ref ICurrentAction currentAction, Dictionary<string, object> parameters)
        {

        }
    }
}
